package com.zyl.blog.processing.util;

import com.zyl.blog.processing.exception.FileProcessingException;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件处理工具类
 * 提供通用的文件处理辅助方法
 * 
 * @author FinalFantasy
 * @version v1.0
 * @date 2025/09/01
 */
public final class FileProcessingUtils {

    private FileProcessingUtils() {
        // 工具类不允许实例化
    }

    /**
     * 常见文件类型MIME映射
     */
    private static final Map<String, String> MIME_TYPE_MAP = new HashMap<>();
    
    static {
        // PDF
        MIME_TYPE_MAP.put("pdf", "application/pdf");
        
        // Word文档
        MIME_TYPE_MAP.put("doc", "application/msword");
        MIME_TYPE_MAP.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        
        // Excel文档
        MIME_TYPE_MAP.put("xls", "application/vnd.ms-excel");
        MIME_TYPE_MAP.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        
        // 文本文件
        MIME_TYPE_MAP.put("txt", "text/plain");
        MIME_TYPE_MAP.put("md", "text/markdown");
        MIME_TYPE_MAP.put("html", "text/html");
        MIME_TYPE_MAP.put("xml", "text/xml");
        
        // 图片文件
        MIME_TYPE_MAP.put("jpg", "image/jpeg");
        MIME_TYPE_MAP.put("jpeg", "image/jpeg");
        MIME_TYPE_MAP.put("png", "image/png");
        MIME_TYPE_MAP.put("gif", "image/gif");
    }

    /**
     * 从文件名提取文件扩展名
     * @param fileName 文件名
     * @return 文件扩展名（小写，不含点）
     */
    public static String getFileExtension(String fileName) {
        if (fileName == null || fileName.trim().isEmpty()) {
            throw new FileProcessingException("文件名为空");
        }
        
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex <= 0 || lastDotIndex == fileName.length() - 1) {
            throw new FileProcessingException("无法确定文件类型: " + fileName);
        }
        
        return fileName.substring(lastDotIndex + 1).toLowerCase();
    }

    /**
     * 根据文件扩展名获取MIME类型
     * @param fileExtension 文件扩展名
     * @return MIME类型
     */
    public static String getMimeType(String fileExtension) {
        return MIME_TYPE_MAP.getOrDefault(fileExtension.toLowerCase(), "application/octet-stream");
    }

    /**
     * 替换文件扩展名
     * @param fileName 原文件名
     * @param newExtension 新扩展名
     * @return 新文件名
     */
    public static String replaceFileExtension(String fileName, String newExtension) {
        if (fileName == null || fileName.trim().isEmpty()) {
            return "file." + newExtension;
        }
        
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0) {
            return fileName.substring(0, lastDotIndex) + "." + newExtension;
        } else {
            return fileName + "." + newExtension;
        }
    }

    /**
     * 截断文本到指定长度
     * @param text 原文本
     * @param maxLength 最大长度
     * @return 截断后的文本
     */
    public static String truncateText(String text, int maxLength) {
        if (text == null) {
            return "";
        }
        if (maxLength <= 0) {
            return "";
        }
        if (text.length() <= maxLength) {
            return text;
        }
        return text.substring(0, maxLength) + "...";
    }

    /**
     * 清理文本内容（移除多余空白字符）
     * @param text 原文本
     * @return 清理后的文本
     */
    public static String cleanText(String text) {
        if (text == null) {
            return "";
        }
        
        return text
            .replaceAll("\\r\\n|\\r|\\n", "\n")  // 统一换行符
            .replaceAll("\\n{3,}", "\n\n")       // 合并多个换行符
            .replaceAll("[ \\t]+", " ")          // 合并多个空格和制表符
            .trim();
    }

    /**
     * 验证文件大小是否在允许范围内
     * @param fileSize 文件大小（字节）
     * @param maxSize 最大允许大小（字节）
     * @return 是否合法
     */
    public static boolean isFileSizeValid(long fileSize, long maxSize) {
        return fileSize > 0 && fileSize <= maxSize;
    }

    /**
     * 格式化文件大小为人类可读形式
     * @param sizeInBytes 文件大小（字节）
     * @return 格式化后的大小字符串
     */
    public static String formatFileSize(long sizeInBytes) {
        if (sizeInBytes < 0) {
            return "未知";
        }
        
        final String[] units = {"B", "KB", "MB", "GB", "TB"};
        double size = sizeInBytes;
        int unitIndex = 0;
        
        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }
        
        return String.format("%.1f %s", size, units[unitIndex]);
    }

    /**
     * 检查文件扩展名是否在支持列表中
     * @param fileExtension 文件扩展名
     * @param supportedTypes 支持的类型列表
     * @return 是否支持
     */
    public static boolean isFileTypeSupported(String fileExtension, List<String> supportedTypes) {
        if (fileExtension == null || supportedTypes == null) {
            return false;
        }
        return supportedTypes.contains(fileExtension.toLowerCase());
    }

    /**
     * 从字符串内容创建MultipartFile
     * @param content 字符串内容
     * @param fileName 文件名
     * @param contentType 内容类型
     * @return MultipartFile实例
     */
    public static MultipartFile createMultipartFileFromString(String content, String fileName, String contentType) {
        if (content == null) {
            content = "";
        }
        if (contentType == null) {
            contentType = "text/plain";
        }
        
        byte[] bytes = content.getBytes(StandardCharsets.UTF_8);

        String finalContentType = contentType;
        return new MultipartFile() {
            @Override
            public String getName() {
                return "generatedFile";
            }

            @Override
            public String getOriginalFilename() {
                return fileName;
            }

            @Override
            public String getContentType() {
                return finalContentType;
            }

            @Override
            public boolean isEmpty() {
                return bytes.length == 0;
            }

            @Override
            public long getSize() {
                return bytes.length;
            }

            @Override
            public byte[] getBytes() {
                return bytes.clone();
            }

            @Override
            public InputStream getInputStream() {
                return new ByteArrayInputStream(bytes);
            }

            @Override
            public void transferTo(File dest) throws IOException, IllegalStateException {
                try (FileOutputStream fos = new FileOutputStream(dest)) {
                    fos.write(bytes);
                }
            }
        };
    }

    /**
     * 安全地关闭资源
     * @param closeable 可关闭的资源
     */
    public static void closeQuietly(AutoCloseable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception e) {
                // 静默关闭，不抛出异常
            }
        }
    }

    /**
     * 统计文本中的基本信息
     * @param text 文本内容
     * @return 统计信息
     */
    public static Map<String, Object> analyzeText(String text) {
        Map<String, Object> stats = new HashMap<>();
        
        if (text == null) {
            text = "";
        }
        
        // 基本统计
        stats.put("characterCount", text.length());
        stats.put("lineCount", text.isEmpty() ? 0 : text.split("\n").length);
        
        // 单词统计（简单按空白字符分割）
        String[] words = text.trim().split("\\s+");
        stats.put("wordCount", text.trim().isEmpty() ? 0 : words.length);
        
        // 段落统计（按双换行符分割）
        String[] paragraphs = text.split("\n\\s*\n");
        stats.put("paragraphCount", text.trim().isEmpty() ? 0 : paragraphs.length);
        
        return stats;
    }

    /**
     * 验证文件名是否安全（防止路径遍历攻击）
     * @param fileName 文件名
     * @return 是否安全
     */
    public static boolean isFileNameSafe(String fileName) {
        if (fileName == null || fileName.trim().isEmpty()) {
            return false;
        }
        
        // 检查是否包含路径遍历字符
        List<String> dangerousPatterns = Arrays.asList(
            "..", "/", "\\", ":", "*", "?", "\"", "<", ">", "|"
        );
        
        for (String pattern : dangerousPatterns) {
            if (fileName.contains(pattern)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * 清理文件名，移除危险字符
     * @param fileName 原文件名
     * @return 清理后的文件名
     */
    public static String sanitizeFileName(String fileName) {
        if (fileName == null) {
            return "file";
        }
        
        // 替换危险字符为下划线
        return fileName
            .replaceAll("[/\\\\:*?\"<>|]", "_")
            .replaceAll("\\.{2,}", ".")
            .trim();
    }
}